package class08

import "fmt"

/*
	一种消息接收并打印的结构设计
	一直一个消息流会不断地突出整数 1~N，但不一定按照顺序吐出。如果上次打印的数
	为i，那么当i+1出现时，请打印i+1及其之后接收过的并且连续的所有数，直到1~N全
	部接收并打印完，请设计这种接收并打印的结构，初始时默认i==0

	算法流程：
	1. 将数字包装成一个个的节点
		node {
			value: number，
			next：*node
		}

	2. 形成两个 map[int]Node, 一个叫做 start 一个叫做 tail

	3. 将节点插入 start 与 tail，两个队列里头都有节点自己，并且 start 的 next 指向自己

	4. tail 判断 该节点后面的数字是否存在tail中，如果存在，则将该节点的next指向后继节点，并将自身节点删除
	start     tail

	5. start 判断该节点，前面的数字是否存在 start 中， 如果存在，则将前面节点的next指向自己，自己则从start队伍中删除
*/
func NewMessageBox() MessageBox {
	return MessageBox{
		headMap: make(map[int]*Node),
		tailMap: make(map[int]*Node),
		waitPoint: 1,
	}
}

type MessageBox struct {
	headMap   map[int]*Node
	tailMap   map[int]*Node
	waitPoint int
}

type Node struct {
	Info  string
	Next *Node
}

func (m *MessageBox)Receive(num int, info string) {
	if num < 1 {
		return
	}
	// 1. 将节先放入两个map中
	n := &Node{Info: info}
	m.tailMap[num] = n
	m.headMap[num] = n

	/*
		7    9

	*/

	// 2. 判断该节点在 tailMap  中是否存在后继节点，存在则链接，并删除自身删除
	if pre, ok := m.tailMap[num-1]; ok {
		pre.Next = n
		delete(m.tailMap, num-1)
		delete(m.headMap, num)
	}

	// 3. 判断该节点在 headMap  中是否存在头节点的前继节点，存在，则链接，并将自身删除
	if next, ok := m.headMap[num+1]; ok {
		n.Next = next
		delete(m.tailMap, num)
		delete(m.headMap, num+1)
	}

	// 4. 判断是否打印
	if num == m.waitPoint {
		printNode := m.headMap[num]
		delete(m.headMap, num)
		for printNode != nil {
			fmt.Println(printNode.Info)
			printNode = printNode.Next
			m.waitPoint++
		}
		delete(m.tailMap, m.waitPoint-1)
	}
}
